<template>
	<diyNavVue :title="toInfo.name"></diyNavVue>
	<view class="page-content">
		<view class="message-list">
			<view :class="['message-item', item.fromId === meId ? 'right': '']" v-for="(item, index) in messageList"
				:key="index">
				<image v-if="item.fromId!==meId" class="message-avatar" :src="toInfo.avatar" mode=""></image>
				
				<rich-text v-if="typeof(item.message)=='string'" :nodes="item.message"></rich-text>
				<template v-else>
					<up-icon v-if="item.message.type==='audio'" @click="playRecorder(item.message)" name="mic" size="40" color="#2979ff"></up-icon>
				</template>
				<image v-if="item.fromId===meId" class="message-avatar" :src="myInfo.avatar" mode=""></image>
			</view>
		</view>
	</view>
	<view class="footer">
		<view class="input-model">
			<up-icon name="volume" size="28" color="#2979ff" @longpress="startRecoder" @touchend="stopRecorder"></up-icon>
			<up-input v-model="messageValue" placeholder="请输入内容" clearable></up-input>
			<button size="mini" type="primary" @click="doSend">发送</button>
			<up-icon name="star-fill" color="#2979ff" size="28" @click="handleIcon"></up-icon>
			<up-icon name="photo" color="#2979ff" size="28" @click="selectImg"></up-icon>
		</view>
		<view class="icon-list" v-if="showIcon">
			<image @click="selectIcon(item)" class="icon-item" :src="item.url" mode="" v-for="item in iconList"></image>
		</view>
	</view>
</template>

<script setup>
	import {
		ref
	} from 'vue'
	import io from '@hyoga/uni-socket.io';
	import diyNavVue from '../../components/diy-nav/diy-nav.vue';
	import {
		onLoad
	} from '@dcloudio/uni-app'
	// 定义静态的表情列表的响应式数据
	const iconList = ref([
		{url: '/static/icon/bs.png', code: '/bs'},
		{url: '/static/icon/cj.png', code: '/cj'},
		{url: '/static/icon/eye.png', code: '/eye'},
		{url: '/static/icon/sq.png', code: '/sq'},
		{url: '/static/icon/yg', code: '/yg'},
	])
	// 控制图片列表是否展示的变量
	const showIcon = ref(false)
	
	// 定义静态人员列表数据模拟接口查询人员信息
	const personList = [{
			id: 'bin',
			name: '李少斌',
			avatar: 'http://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280'
		},
		{
			id: 'zxy',
			name: '张学友',
			avatar: 'http://gips3.baidu.com/it/u=1821127123,1149655687&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280'
		},
		{
			id: 'ldh',
			name: '刘德华',
			avatar: 'http://gips3.baidu.com/it/u=100751361,1567855012&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280'
		},
		{
			id: 'lm',
			name: '黎明',
			avatar: 'http://gips1.baidu.com/it/u=3874647369,3220417986&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280'
		}
	]
	// 重新连接次数
	let times = 0
	// 客户端链接socket服务的socket实例
	let socket = null
	// 定义定时器变量
	let timer
	// 定义心跳检测的方法
	const doHeart = () => {
		// 重置定时器，做心跳检测
		timer && clearInterval(timer)
		timer = setInterval(() => {
			socket.emit('ping')
		}, 20000)
	}
	// 创建方法，链接socket服务
	const linkSocket = () => {
		console.log('1')
		socket = io('ws://localhost:3000', {
			path: '/mysocket',
			query: {
				// 连接socket服务的时候，把自己的id传进去
				id: meId.value
			},
			reconnection: false,
			transports: ['websocket', 'polling'],
			timeout: 5000,
		});
		// 客户端监听连接成功的事件
		socket.on('connect', () => {
			// 每隔一段时间发送一个消息
			doHeart()
			console.log('客户端链接socket服务成功')
			// 注册接收消息的事件
			socket.on('reciveMsg', (info) => {
				console.log(info)
				messageList.value.push(info)
			})
			// 注册心跳检测的响应事件
			socket.on('pang', () => {
				console.log('完成一次心跳检测');
			})
		})
		// 断线重连：已经连接得状态，突然断开进行尝试重新连接
		socket.on('disconnect', () => {
			console.log('链接断开了')
			linkSocket()
		})
		// 断线重连：当前没有连接上，链接的时候出现错误
		socket.on('connect_error', () => {
			console.log('链接的时候出现了未知错误')
			if(times>9) {
				return uni.$u.toast(`已经重新连接了${times}次`)
			}
			times += 1
			linkSocket()
		})
	}
	const messageList = ref([])
	//分别定义响应式对象保存我的和对方的信息
	const myInfo = ref({})
	const toInfo = ref({})

	// 定义一个响应式的变量来缓存我的id
	const meId = ref('')
	// 定义一个响应式的变量来缓存对方的id
	const toId = ref('')
	
	// 定义响应式变量获取输入框内容
	const messageValue = ref('')
	// 从url里面获取参数
	onLoad((options) => {
		console.log('2')
		console.log(options)
		meId.value = options.meId
		toId.value = options.toId
		getUserInfo()
		linkSocket()
	})
	// 实现目标字符串匹配表情关键字，并替换成img标签的方法
	const codeToImgStr = (str) => {
		let newStr = str
		iconList.value.forEach(item => {
			// item => {url: '', code: ''}
			// 匹配目标字符串中的表情关键字，把表情关键字替换成img标签字符串，并赋予对应的表情图片地址
			// ！！！replaceAll方法不会修改原字符串，会生成一个新的字符串
			newStr = newStr.replaceAll(item.code, `<img style="width: 40px;height:40px;" src="${item.url}">`)
		})
		return newStr
	}
	// 点击发送
	const doSend = () => {
		
		// 构造消息对象
		// 构造消息对象中消息内容的时候，判断如果字符匹配到了某个表情的关键字
		// 把匹配到的表情关键字替换为img标签
		const messageObj = {
			fromId: meId.value,
			toId: toId.value,
			message: codeToImgStr(messageValue.value)
		}
		// 点击发送的时候，向messageList消息列表里面push消息对象
		messageList.value.push(messageObj)
		// 通过socket实例触发服务端注册(监听的事件)来发送消息
		socket.emit('sendMsg', messageObj)
		// 消息发送完，把输入框里面内容清空掉
		messageValue.value = ''
	}
	
	
	// 获取用户信息的方法
	const getUserInfo = () => {
		// 从personList数组中查找 id===meId 的元素就是我的信息
		myInfo.value = personList.find(item => item.id === meId.value) || {}
		// 查找对方的
		toInfo.value = personList.find(item => item.id === toId.value) || {}
	}
	
	// 控制表情列表展示/隐藏的方法
	const handleIcon = () => {
		showIcon.value = !showIcon.value
	}
	// 选中表情的事件方法
	const selectIcon  = item => {
		messageValue.value += item.code
	}
	
	// 点击选择图片的方法
	const selectImg = () => {
		uni.chooseImage({
			success(res) {
				console.log(res)
				setTimeout(() => {
					const url = 'http://gips1.baidu.com/it/u=3874647369,3220417986&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280'
					const messageObj = {
						fromId: meId.value,
						toId: toId.value,
						message: `<img style="width: 100px;height: auto;" src="${url}" >`
					}
					// 把消息对象添加到消息列表中
					messageList.value.push(messageObj)
					// 发送消息
					socket.emit('sendMsg', messageObj)
				}, 2000)
			}
		})
	}
	// 实例化全局唯一的录音管理器
	const recorderManage = uni.getRecorderManager()
	
	recorderManage.onStop((res) => {
		console.log(res)
		// 拿到录音文件临时路径，进行上传
		setTimeout(() => {
			const url = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3'
			// 构造音频消息对象
			const messageObj = {
				fromId: meId.value,
				toId: toId.value,
				message: {
					type: 'audio',
					url
				}
			}
			// 添加到自己的聊天列表
			messageList.value.push(messageObj)
			// 发送消息到服务端
			socket.emit('sendMsg', messageObj)
		}, 2000)
	})
	// 长按开始录音
	const startRecoder = () => {
		recorderManage.start()
	}
	// 触摸结束 停止录音
	const stopRecorder = () => {
		recorderManage.stop()
	}
	
	// 创建audio上下文对象
	const audioContext = uni.createInnerAudioContext()
	// 语音消息，点击播放
	const playRecorder = ({url}) => {
		console.log(url)
		console.log(audioContext.paused)
		audioContext.src = url
		// 点击的时候如果是正在播放的状态，则停止
		if(!audioContext.paused) {
			audioContext.pause()
		} else {// 否则的话播放
			audioContext.play()
		}
		
	}
</script>

<style lang="scss" scoped>
	.page-content {
		padding-top: 140rpx;
		padding-bottom: 80rpx;
	}

	.footer {
		position: fixed;
		bottom: 0;
		width: 100vw;
	}

	.message-list {
		.message-item {
			display: flex;

			.message-avatar {
				width: 30rpx;
				height: 30rpx;
			}

			&.right {
				justify-content: flex-end;
			}
		}
	}

	.input-model {
		display: flex;
		align-items: center;
	}
	.icon-list {
		padding: 20rpx;
		.icon-item{
			width: 40rpx;
			height: 40rpx;
			margin: 0 20rpx;
		}
	}
</style>